package org.wx.herostory.services.db.login;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.wx.herostory.services.db.MySqlSessionFactory;
import org.wx.herostory.services.processor.async.AsyncOperationProcessor;
import org.wx.herostory.services.processor.async.IAsyncOperation;
import org.wx.herostory.services.util.RedisUtil;
import redis.clients.jedis.Jedis;

import java.util.function.Function;


/**
 * 登陆服务
 */
@Slf4j
public final class LoginService {


    /**
     * 单例对象
     */
    static private final LoginService _instance = new LoginService();

    /**
     * 私有化类默认构造器
     */
    private LoginService() {
    }

    /**
     * 获取单例对象
     *
     * @return
     */
    static public LoginService getInstance() {
        return _instance;
    }

    /**
     * 用户登陆
     *
     * @param userName
     * @param password
     * @return
     */
    public void userLogin(String userName, String password, Function<UserEntity,Void> callback) {
        if (null == userName ||
            null == password) {
            return ;
        }
        AsyncOperationProcessor.getInstance().process(new AsyncLoginOperation(userName,password,callback));

    }

    static private class AsyncLoginOperation implements IAsyncOperation {

        private String userName;

        private String password;

        private UserEntity userEntity;

        Function<UserEntity,Void> callback;


        public AsyncLoginOperation(String userName, String password,Function<UserEntity,Void> callback) {
            this.userName = userName;
            this.password = password;
            this.callback = callback;
        }

        @Override
        public void doAsync() {
            try (SqlSession mySqlSession = MySqlSessionFactory.openSession()) {
                // 获取 DAO
                IUserDao dao = mySqlSession.getMapper(IUserDao.class);
                // 获取用户实体
                UserEntity userEntity = dao.getByUserName(userName);

                log.info("当前线程 = {}", Thread.currentThread().getName());

                if (null != userEntity) {
                    if (!password.equals(userEntity.password)) {
                        throw new RuntimeException("密码错误");
                    }
                } else {
                    userEntity = new UserEntity();
                    userEntity.userName = userName;
                    userEntity.password = password;
                    userEntity.heroAvatar = "Hero_Shaman";

                    dao.insertInto(userEntity);
                }

                 this.userEntity = userEntity;
                 getInstance().updateUserInfoInRedis(userEntity);
            } catch (Exception ex) {
                // 记录错误日志
                log.error(ex.getMessage(), ex);

            }
        }

        /**
         * 完成后，执行监听回调
         */
        @Override
        public void doFinish() {
            if(null != userEntity){
                callback.apply(userEntity);
            }
        }

        @Override
        public int getBindId() {
            if (null == userName) {
                return 0;
            } else {
                return userName.charAt(userName.length() - 1);
            }
        }
    }

    /**
     * 用户登录成功更新Redis中的用户信息
     * @param userEntity
     */
    private void updateUserInfoInRedis(UserEntity userEntity) {
        if(null == userEntity){
            return;
        }
        // try() 这种写法可以执行之后自动调用close方法关闭资源(对象)要实现Closeable接口
        try (Jedis jedis = RedisUtil.getJedis()){
            final JSONObject jsonObject = new JSONObject();
            jsonObject.put("userName", userEntity.userName);
            jsonObject.put("heroAvatar", userEntity.heroAvatar);
            // 存入redis
            jedis.hset("User_" + userEntity.userId, "BasicInfo", jsonObject.toString());
        }
    }
}
